package models

import (
	"encoding/json"
	"fmt"
	"gitchina/kly_mall/data"
	"gitchina/kly_mall/errors"
	"gitchina/kly_mall/util"
)

const (
	FUNC_CATEGORY_LOAD                 = "preload.onCategoryLoad"
	FUNC_ALL_ATTRIBUTE_LOAD            = "preload.allAttrLoad"
	FUNC_ATTRIBUTE_LOAD_BY_CATEGORY_ID = "preload.attrLoadByCategoryID"
)

func PreloadInit() {
	util.Sub(util.NOTIFY_CATEGORY_LOAD).On(categoryLoad).Failed(failed)
	util.Sub(util.NOTIFY_ATTRIBUTE_LOAD).On(categoryAttrLoad).Failed(failed)
	util.Event{Name: util.NOTIFY_CATEGORY_LOAD}.Pub()
	util.Event{Name: util.NOTIFY_ATTRIBUTE_LOAD}.Pub()
}

func categoryLoad(v interface{}) errors.Error {
	var err error
	var jsond []byte
	var list []data.Category

	if list, err = data.GetCategoryList(); err != nil {
		return errors.New(FUNC_CATEGORY_LOAD, err.Error())
	}
	categories := util.MapFrom(list).
		Take("ID", "ParentID", "Name", "Desc", "MeasureUnit").
		To(Category{})

	if jsond, err = json.Marshal(categories); err != nil {
		return errors.New(FUNC_CATEGORY_LOAD, err.Error())
	}
	redis := util.NewRedis(RedisAddr())
	if resp := redis.Cmd("set", CATEGORY_CACHE_KEY, jsond); resp.Err != nil {
		return errors.New(FUNC_CATEGORY_LOAD, resp.Err.Error())
	}
	return errors.Null()
}

func categoryAttrLoad(v interface{}) errors.Error {
	var err errors.Error
	if v == nil {
		err = allAttrLoad()
	} else {
		err = attrLoadByCategoryID(v.(int64))
	}
	return err
}

func allAttrLoad() errors.Error {
	var ok bool
	var err error
	var jsond []byte
	var attrs []data.Attribute
	var list []*Attribute

	group := make(map[int64][]*Attribute)

	if attrs, err = data.GetAttributeList(); err != nil {
		return errors.New(FUNC_ALL_ATTRIBUTE_LOAD, err.Error())
	}

	for _, attr := range attrs {
		if _, ok = group[attr.CategoryID]; !ok {
			list = make([]*Attribute, 0)
		}
		mapped := util.MapFrom(attr).
			Take("ID", "Name", "InputType", "Type", "Values").
			To(Attribute{})
		list = append(list, mapped.(*Attribute))
		group[attr.CategoryID] = list
	}

	redis := util.NewRedis(RedisAddr())
	for k, v := range group {
		if jsond, err = json.Marshal(v); err != nil {
			return errors.New(FUNC_ALL_ATTRIBUTE_LOAD, err.Error())
		}
		if resp := redis.Cmd("set", fmt.Sprintf("%s_%d", CATEGORY_ATTRIBUTE_CACHE_KEY, k), jsond); resp.Err != nil {
			return errors.New(FUNC_ALL_ATTRIBUTE_LOAD, resp.Err.Error())
		}
	}

	return errors.Null()
}

func attrLoadByCategoryID(categoryID int64) errors.Error {
	var err error
	var jsond []byte
	var list []data.Attribute

	if list, err = data.GetAttributeListByCategoryID(categoryID); err != nil {
		return errors.New(FUNC_ATTRIBUTE_LOAD_BY_CATEGORY_ID, err.Error())
	}

	attrs := util.MapFrom(list).
		Take("ID", "Name", "InputType", "Type", "Values").
		To(Attribute{})

	if jsond, err = json.Marshal(attrs); err != nil {
		return errors.New(FUNC_ATTRIBUTE_LOAD_BY_CATEGORY_ID, err.Error())
	}
	redis := util.NewRedis(RedisAddr())
	if resp := redis.Cmd("set", fmt.Sprintf("%s_%d", CATEGORY_ATTRIBUTE_CACHE_KEY, categoryID), jsond); resp.Err != nil {
		return errors.New(FUNC_ATTRIBUTE_LOAD_BY_CATEGORY_ID, resp.Err.Error())
	}
	return errors.Null()
}

func failed(err errors.Error) {
	util.WriteLog(err)
}
